require 'chess-data'
require 'minitest/autorun'

describe ChessData::Board do
  it "must set up an empty board on new" do
    board = ChessData::Board.new
    8.times do |i|
      8.times do |j|
        square = (65+i).chr + (49+j).chr
        _(board[square]).must_be_nil
      end
    end
  end

  it "must raise an ArgumentError on invalid squares" do
    board = ChessData::Board.new
    _(proc {board["9"]}).must_raise ArgumentError
    _(proc {board["E9"]}).must_raise ArgumentError
  end

  it "must raise ArgumentError on invalid FEN" do
    _(proc {ChessData::Board.from_fen("1 2 3")}).must_raise ArgumentError
  end

  it "must set up valid FEN position correctly" do
    board = ChessData::Board.from_fen "3k4/7p/8/8/8/8/2P5/R7 b Kq - 5 46"
    _(board[:A1]).must_equal "R"
    _(board[:C2]).must_equal "P"
    _(board[:H7]).must_equal "p"
    _(board[:D8]).must_equal "k"
    _(board.to_move).must_equal "b"
    _(board.white_king_side_castling).must_equal true
    _(board.white_queen_side_castling).must_equal false
    _(board.black_king_side_castling).must_equal false
    _(board.black_queen_side_castling).must_equal true
    _(board.enpassant_target).must_equal "-"
    _(board.halfmove_clock).must_equal 5
    _(board.fullmove_number).must_equal 46
  end
  
  it "must clone a board correctly" do
    board = ChessData::Board.from_fen "3k4/7p/8/8/8/8/2P5/R7 b Kq - 5 46"
    clone = board.clone
    _(clone[:A1]).must_equal "R"
    _(clone[:C2]).must_equal "P"
    _(clone[:H7]).must_equal "p"
    _(clone[:D8]).must_equal "k"
    _(clone.to_move).must_equal "b"
    _(clone.white_king_side_castling).must_equal true
    _(clone.white_queen_side_castling).must_equal false
    _(clone.black_king_side_castling).must_equal false
    _(clone.black_queen_side_castling).must_equal true
    _(clone.enpassant_target).must_equal "-"
    _(clone.halfmove_clock).must_equal 5
    _(clone.fullmove_number).must_equal 46
  end

  it "must create valid start position" do
    board = ChessData::Board.start_position
    _(board[:A1]).must_equal "R"
    _(board[:E8]).must_equal "k"
    _(board[:E2]).must_equal "P"
    _(board[:A8]).must_equal "r"
    _(board[:E4]).must_be_nil
  end

  it "must see a clone as equal" do
    board = ChessData::Board.start_position
    _(board.clone).must_equal board
  end

  it "must see two boards with small changes as different: Q" do
    board = ChessData::Board.start_position
    board.white_queen_side_castling = false
    _(board).wont_equal ChessData::Board.start_position
  end

   it "must see two boards with small changes as different: half-move" do
    board = ChessData::Board.start_position
    board.halfmove_clock = 5
    _(board).wont_equal ChessData::Board.start_position
  end

   it "must see two boards with small changes as different: Pe4" do
    board = ChessData::Board.start_position
    board[:e4] = "P"
    _(board).wont_equal ChessData::Board.start_position
  end

   it "must retrieve locations of pawns in start position" do
     board = ChessData::Board.start_position
     _(board.locations_of("P").length).must_equal 8
     _(board.locations_of("P")).must_include "A2"
     _(board.locations_of("P")).must_include "B2"
     _(board.locations_of("P")).must_include "C2"
     _(board.locations_of("P")).must_include "D2"
     _(board.locations_of("P")).must_include "E2"
     _(board.locations_of("P")).must_include "F2"
     _(board.locations_of("P")).must_include "G2"
     _(board.locations_of("P")).must_include "H2"
   end

   it "must retrieve locations of knights in start position" do
     board = ChessData::Board.start_position
     _(board.locations_of("n").length).must_equal 2
     _(board.locations_of("n")).must_include "B8"
     _(board.locations_of("n")).must_include "G8"
   end
   
   it "must retrieve locations of knights in start position filtered by rank" do
     board = ChessData::Board.start_position
     _(board.locations_of("n", "B").length).must_equal 1
     _(board.locations_of("n")).must_include "B8"
   end

   it "must count pieces on the board" do
     board = ChessData::Board.start_position
     _(board.count("K")).must_equal 1
     _(board.count("n")).must_equal 2
     _(board.count("P")).must_equal 8
     _(board.count("O")).must_equal 0
   end
end

